package elsim.simulator

import elsim.entities.Passenger;

import com.google.common.collect.Ordering;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;

import com.google.common.collect.Iterables;

import elsim.common.Clock;
import elsim.controller.Controller;
import elsim.controller.EventController;
import elsim.entities.Lift;
import elsim.entities.LiftManager;
import elsim.entities.PassengerAlgorithms;
import elsim.events.DisplayEvent;
import elsim.events.CallEvent;
import elsim.events.Event
import elsim.events.EventQueue;
import elsim.events.FailEvent;
import elsim.events.FixEvent;
import elsim.scenarios.ScenarioReader;

class ElevatorSimulator {
  private static final Logger LOG = Logger.getLogger(ElevatorSimulator.class)

  static List<String> scenario = [
    "StartTime:\t09:00:00",
    "NumberOfFloors:\t5",
    "NumberOfElevators:\t3",
    "init\t0\t0",
    "init\t1\t0",
    "init\t2\t3",
    "display\t09:00:00",
    "call\tsgzmd\t3\t09:00:10\t0",
    "display\t09:00:50",
    "display\t09:02:50",
  ]

  /**
   * This method assumes event queue is already populated
   */
  public void runSimulation() {
    def eventQueue = EventQueue.getEventQueue()
    def clock = Clock.clock

    while (!eventQueue.isEmpty()) {
      Event event = eventQueue.accept();
      while (clock.clockValue < event.eventTime) {
        clock.tick()
      }

      dispatchEvent(event);
    }
  }

  public void dispatchEvent(DisplayEvent event) {
    LOG.info("DisplayEvent: " + event.toString())
    for (Lift lift : LiftManager.getLiftManager().lifts) {
      System.err.println(lift.toString());
    }
  }

  public void dispatchEvent(CallEvent event) {
    Lift bestLift = PassengerAlgorithms.findBestLift(LiftManager.getLiftManager().getLifts(), event.from, event.to)
    bestLift.addPendingRequest(new Passenger(event.name, event.from, event.to))
  }

  public void dispatchEvent(FailEvent event) {
    LOG.info("FailEvent: " + event.toString())
  }

  public void fixEvent(FixEvent event) {
    LOG.info("FixEvent: " + event.toString())
  }

  public static void main(String[] args) {
    BasicConfigurator.configure();
    Logger.getRootLogger().setLevel Level.DEBUG

    // simulating, in real-world we'll just wait forever
    Controller controller = new EventController()
    ScenarioReader reader = new ScenarioReader(scenario, controller)
    reader.readScenario()

    new ElevatorSimulator().runSimulation();
  }
}
